<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 函数柯里化（Currying）是函数式编程中的一个概念，它将一个接受多个参数的函数转换为一系列接受单个参数的函数。
        // 换句话说，柯里化的函数会逐步接收参数，每次接收一个参数，并返回一个新的函数来接收下一个参数，
        // 直到所有参数都被接收为止，最终返回结果。


        // 参数重用：柯里化可以方便地固定住某些参数，然后生成一个新的函数，这样可以在多次调用时减少重复传递参数的麻烦。

        // 延迟计算：通过柯里化可以延迟函数的执行，直到所有参数都传递完毕。

        // 函数组合：柯里化使得函数组合更加容易，从而提升代码的模块化和复用性。

        // 简单示例
            // 普通加法函数
            function add(a, b) {
                return a + b;
            }

            // 柯里化后的加法函数
            function curriedAdd(a) {
                return function(b) {
                    return a + b;
                };
            }

            console.log(add(2, 3));       // 5
            console.log(curriedAdd(2)(3)); // 5

        // 柯里化的实现
            // 手动实现简单柯里化
            function curry(fn) {
                return function curried(a) {
                    return function(b) {
                        return fn(a, b);
                    };
                };
            }

            const curriedAdd = curry(add);
            console.log(curriedAdd(2)(3)); // 5
            // 通用柯里化实现
            function curry(fn) {
                return function curried(...args) {
                    // 如果参数数量足够，直接调用原函数
                    if (args.length >= fn.length) {
                        return fn.apply(this, args);
                    } 
                    // 否则返回一个新函数，接收剩余参数
                    else {
                        return function(...args2) {
                            return curried.apply(this, args.concat(args2));
                        };
                    }
                };
            }

            // 测试
            function sum(a, b, c) {
                return a + b + c;
            }

            const curriedSum = curry(sum);
            console.log(curriedSum(1)(2)(3));     // 6
            console.log(curriedSum(1, 2)(3));     // 6
            console.log(curriedSum(1)(2, 3));     // 6
            console.log(curriedSum(1, 2, 3));     // 6
    </script>
</body>
</html>